let code = require('../../../constant/code');
let token = require('../../../util/token');
let userDao = require('../../../dao/userDao');
let logger = require('pomelo-logger').getLogger('logic');
let userInfoServices = require('../../../services/userInfoServices');
let pomeloServices = require('../../../services/pomeloServices');
let configServices = require('../../../services/configServices');
let dispatch = require('../../../util/dispatcher');
let rpcAPI = require('../../../API/rpcAPI');
let commonDao = require('../../../dao/commonDao');
let pushAPI = require('../../../API/pushAPI');
let redisService = require('../../../services/redisService');
let pomelo = require('pomelo');

module.exports = function (app) {
    return new Handler(app);
};


let Handler = function (app) {
    this.app = app;
};

//玩家进入
Handler.prototype.entry = async function (msg, session, next) {

    try {

        //logger.info(`user entry data = ${JSON.stringify(msg)}`);
        // 检查服务器状态
        let isAllServerStarted = this.app.get('allServerStarted');
        if (!isAllServerStarted) {
            next(null, { code: code.SERVER_MAINTENANCE });
            return;
        }
        // 检查token
        if (!msg.token) {
            next(null, { code: code.REQUEST_DATA_ERROR });
            return;
        }
        let authInfo = token.parseToken(msg.token);
        if (!token.checkToken(authInfo)) {
            logger.info(`user entry data = ${JSON.stringify(msg)}`);
            next(null, { code: code.TOKEN_INFO_ERROR });
            return;
        }
        let uid = authInfo.uid;

        // let loginKey = uid + '-Login';
        // if (redisService.isLocked(loginKey, 3)) {
        //     redisService.unLock(loginKey);
        //     return;
        // }

        // 获取用户信息
        let userData = await userDao.getUserDataByUid(uid);

        let userInfo = msg.userInfo;
        if (userInfo.nickname && userInfo.nickname.length > 11) {
            userInfo.nickname = userInfo.nickname.slice(0, 11);
        }
        // 检查登录状态
        let sessionService = this.app.get('sessionService');
        let loginUser = await sessionService.getByUid(uid);
        if (loginUser && userData.deviceID != msg.deviceID) {
            //如果用户已经登录 提示已经登录用户退出
            let sid = loginUser[0] && loginUser[0].frontendId;
            pushAPI.kickUserPush({ uid: uid }, [{ uid, sid }]);
        }

        let lastLoginTime = Date.now();
        let checkLogin = function () {
            return new Promise((resolve, reject) => {
                sessionService.kick(uid, function (err) {
                    if (!!err) {
                        logger.error("kick uid err");
                    }
                    session.on('closed', onUserLeave.bind(null, this.app));
                    session.bind(uid, function (err) {
                        if (!!err) {
                            reject(code.FAIL);
                        } else {
                            session.set('lastLoginTime', lastLoginTime);
                            session.pushAll();
                            resolve();
                        }
                    });
                }.bind(this));
            });
        }.bind(this);
        await checkLogin();


        if (!userData) {
            userData = await userInfoServices.createUserThenLoad(uid, userInfo);
        }
        // 检查帐号冻结
        if (!!userData.isBlockedAccount) {
            next(null, { code: code.BLOCKED_ACCOUNT });
            return;
        }
        // 设置房间


        let roomData = {}
        let roomID = "";
        if (userData.roomID) {
            let gameServers = this.app.getServersByType('game');
            let gameServer = dispatch.dispatch(userData.roomID, gameServers);
            let isIn = await rpcAPI.isUserInRoom(gameServer.id, session.uid, userData.roomID);
            if (isIn) {
                roomID = userData.roomID
                roomData.roomID = userData.roomID;
                await pomeloServices.pushSessionData(session, 'roomID', userData.roomID);
                let roomInfo = await rpcAPI.getRoomGameDataByRoomID(gameServer.id, roomID, uid);
                roomData.gameRule = roomInfo.gameRule;
                roomData.roomCreatorInfo = roomInfo.creatorInfo;
                roomData.gameData = roomInfo.gameData;
                roomData.roomUserInfoArr = roomInfo.roomUserInfoArr;
            }
        }


        // 更新用户信息
        let updateUserData = {
            syncLock: 0,            // 登录时清除金币锁，防止数据锁死
            lastLoginIP: sessionService.getClientAddressBySessionId(session.id).ip.split(':').pop(),
            lastLoginTime: lastLoginTime,
            frontendId: this.app.getServerId(),
            roomID: roomID
        };
        if (userData.account == '' || userData.mobilePhone == '') {
            let accountData = await commonDao.findOneData("accountModel", { uid: uid });
            if (accountData) {
                updateUserData.account = accountData.account;
                updateUserData.mobilePhone = accountData.phoneAccount;
            }
        }
        if (!!userInfo && userInfo.nickname) updateUserData.nickname = userInfo.nickname;
        // if (!!userInfo && userInfo.avatar) updateUserData.avatar = userInfo.avatar;
        if (!!userInfo && userInfo.lastLoginIP) updateUserData.lastLoginIP = userInfo.lastLoginIP;
        if (!!userInfo && ("sex" in userInfo)) updateUserData.sex = userInfo.sex;
        if (!!userInfo && ("address" in userInfo)) updateUserData.address = userInfo.address;
        if (msg.deviceID) updateUserData.deviceID = msg.deviceID;
        let newEmailArr = userInfoServices.getNewUserEmail(userData.emailArr, userData.lastLoginTime);
        if (!!newEmailArr) updateUserData.emailArr = newEmailArr;
        userData = await userDao.updateUserDataByUid(uid, updateUserData);
        if (userData.nickname && userData.nickname.length > 8) {
            userData.nickname = userData.nickname.slice(0, 8);
        }

        // logger.error(`[用户登录数据] userData = ${JSON.stringify(userData)}`);
        // userData.gameType = gameType;
        // userData.gameRule = gameRule;
        // userData.creatorInfo = creatorInfo;
        userData.roomData = roomData;
        let config = configServices.buildClientConfig(this.app.get('config'));

        let recordArr = await userInfoServices.getUserUnions(userData);

        next(null, {
            code: code.OK,
            updateUserData: {
                userUnions: recordArr,
                unionInfo: userData.unionInfo
            }, msg: {
                userInfo: userData,
                config: config,
            }
        });
    } catch (err) {
        logger.error('connector entry error:' + err);
        next(null, { code: typeof err !== 'number' ? 500 : err });
    }
};

//玩家登出
Handler.prototype.logout = async function (msg, session, next) {

    try {

        if (!session || !session.uid) return;
        let uid = session.uid;
        logger.info(`[${uid}] logout close session and leave begin`);
        try {
            let userData = await userDao.getUserDataByUid(session.uid);
            if (!userData) {
                logger.error('not find leave user uid:' + session.uid);
            } else {
                if (!!userData.roomID) {
                    let gameServer = dispatch.dispatch(userData.roomID, app.getServersByType('game'));
                    rpcAPI.rpc('game.roomRemote.leaveRoom', gameServer.id, userData.roomID, session.uid, async function (err) { });
                }
                let sessionService = this.app.get('sessionService');
                sessionService.kick(uid);
                await userDao.updateUserDataByUid(session.uid, { frontendId: "" });
            }
        } catch (err) {
            logger.error('onUserLeave error:' + err);
        }
    } catch (err) {
        logger.error('connector entry error:' + err);
        next(null, { code: typeof err !== 'number' ? 500 : err });
    }
};



let onUserLeave = async function (app, session) {

    if (!session || !session.uid) return;
    let uid = session.uid;
    let lastLoginTime = session.get('lastLoginTime');
    logger.info(`[${uid}] close session and leave begin lastLoginTime = ${lastLoginTime}`);

    try {
        let userData = await userDao.updateUserData({ uid: session.uid, lastLoginTime: { '$lte': lastLoginTime } }, { frontendId: "" });
        if (!userData) {
            logger.error('not find leave user uid:' + session.uid);
        } else if (lastLoginTime <= userData.lastLoginTime) {
            //logger.info(`[${uid}] clean data lastLoginTime = ${JSON.stringify(lastLoginTime)} userlastLoginTime = ${JSON.stringify(userData.lastLoginTime)}`);
            if (!!userData.roomID) {
                let gameServer = dispatch.dispatch(userData.roomID, app.getServersByType('game'));
                rpcAPI.rpc('game.roomRemote.leaveRoom', gameServer.id, userData.roomID, session.uid, async function (err) { });
            }
        } else {
            logger.error(`leave wrong lastLoginTime = ${JSON.stringify(lastLoginTime)} userlastLoginTime = ${JSON.stringify(userData.lastLoginTime)}`);
        }
    } catch (err) {
        logger.error('onUserLeave error:' + err);
    }
};